﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MugenInjection;
using MugenInjection.Core;
using MugenInjection.Infrastructure;
using MugenInjection.Interface;
using MugenInjection.Parameters;
using TestModels.Class;
using Should;

namespace MugenInjectionTest.Infrastructure
{
    [TestClass]
    public class DefaultConstructorResolverTest : TestBase
    {
        [TestMethod]
        public void AttributeResolverTest()
        {
            var constructorResolver = new DefaultConstructorResolver();
            var constructorInfo = constructorResolver.Resolve(typeof(ConstructorResolverTestModel), CreateContext());
            constructorInfo.GetParameters().Length.ShouldEqual(3);
        }

        [TestMethod]
        public void ParameterResolverTest()
        {
            Type type = typeof(ConstructorResolverTestModel);
            var setting = new DefaultInjectorSetting { AttributeForInject = typeof(TestMethodAttribute) };

            //Empty parameters
            var constructorResolver = new DefaultConstructorResolver();
            ConstructorInfo constructorInfo = constructorResolver.Resolve(type, CreateContext(setting));
            constructorInfo.GetParameters().Length.ShouldEqual(0);

            //Parameter with one argument
            constructorInfo = constructorResolver
                .Resolve(type, CreateContext(setting, new ConstructorParameter("param1", new object())));
            constructorInfo.GetParameters().Length.ShouldEqual(1);


            //Parameter with two argument
            constructorInfo = constructorResolver
                .Resolve(type, CreateContext(setting,
                                             new ConstructorParameter("param1", new object()),
                                             new ConstructorParameter("param2", new object())
                                   ));
            constructorInfo.GetParameters().Length.ShouldEqual(2);

            //Parameter with three argument
            constructorInfo = constructorResolver
                .Resolve(type, CreateContext(setting,
                                             new ConstructorParameter("param1", new object()),
                                             new ConstructorParameter("param2", new object()),
                                             new ConstructorParameter("param3", new object())
                                   ));
            constructorInfo.GetParameters().Length.ShouldEqual(3);

            //Parameter with three argument(One is empty)
            constructorInfo = constructorResolver
                .Resolve(type, CreateContext(setting,
                                             new ConstructorParameter("param1", new object()),
                                             new ConstructorParameter("param3", new object())
                                   ));
            constructorInfo.GetParameters().Length.ShouldEqual(3);
        }


        [TestMethod]
        public void SetConstructorTest()
        {
            var constructorResolver = new DefaultConstructorResolver();
            var constructorInfo = typeof(Simple).GetConstructor(InjectorUtils.EmptyTypes);
            constructorResolver.SetConstructor(constructorInfo);
            constructorInfo.ShouldEqual(constructorResolver.Resolve(typeof(Simple), CreateContext()));

            //Other type
            constructorInfo.ShouldNotEqual(constructorResolver.Resolve(typeof(SimpleClass), CreateContext()));
        }

        private static IBindingContext CreateContext(IInjectorSettings settings = null,
                                              params IInjectionParameter[] injectionParameters)
        {
            if (settings == null)
                settings = new DefaultInjectorSetting();
            var mugenInjector = new MugenInjector(settings);
            return new BindingContext(typeof(object), null, null, mugenInjector, mugenInjector, injectionParameters,
                                      InjectorUtilsInternal.ReadOnlyEmptyDictionary);
        }
    }
}